package com.fingard.dsp.bank.directbank.abc02;

import com.fingard.client.DspClient;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directbank.bankInterface.IStatement;
import com.fingard.dsp.bank.helpers.FileType;
import com.fingard.dsp.bank.reqrespobj.statement.ReqQryStatement;
import com.fingard.dsp.bank.reqrespobj.statement.RetAtsStatement;
import com.fingard.dsp.bank.reqrespobj.statement.TransState;
import com.fingard.dsp.bank.reqrespobj.statement.detail.RetAtsStatementDetail;
import com.fingard.io.FileHelper;
import com.fingard.net.FtpPortClient;
import com.fingard.net.FtpReceiver;
import com.fingard.net.SftpPortClient;
import com.fingard.net.TcpReceiver;
import com.fingard.text.MFSHelper;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.io.BufferedReader;
import java.io.File;
import java.io.StringReader;
import java.util.ArrayList;

/**
 * 农行对账单
 *
 * @author Cruise
 * @date 2019/4/15
 */
public class ABC02Statement extends ABC02Base implements IStatement {
    @Override
    public RetAtsStatement d_Qry_Statement(ReqQryStatement p_reqQrySttm) throws Exception {
        RetAtsStatement retAts = new RetAtsStatement(p_reqQrySttm);
        retAts.writeStart();

        String[] tmpPosRecRespHeader = getPosRecStatement(p_reqQrySttm, retAts);
        String tmpPosRecTotalNum = getTotalNum(retAts.totalNum);

        String[] hisRecRespHeader = getHisRecStatement(p_reqQrySttm, retAts);
        String hisRectotalNum = getTotalNum(retAts.totalNum);

        if ("-1".equals(tmpPosRecRespHeader[0]) && "-1".equals(hisRecRespHeader[0])) {
            retAts.writeRespCode("-1");
            retAts.writeRespInfo("POS对账单获取失败,原因:" + tmpPosRecRespHeader[1] + ",账户明细文件信息对账单获取失败,原因:" + hisRecRespHeader[1]);
        } else {
            if (retAts.getWrittenRdCount() == 0) {
                retAts.writeRespCode("0");
                String respInfo = tmpPosRecRespHeader[1];
                if (StringHelper.isNullOrEmpty(respInfo)) {
                    respInfo = "交易为空";
                }
                retAts.writeRespInfo(respInfo);
            } else {
                retAts.isWritedTotalNum(String.valueOf(Integer.parseInt(tmpPosRecTotalNum) + Integer.parseInt(hisRectotalNum)));
            }
        }

        retAts.writeEnd();
        return retAts;
    }

    /**
     * POS对账单
     *
     * @param p_reqQrySttm
     * @param retAts
     * @return
     * @throws Exception
     */
    private String[] getPosRecStatement(ReqQryStatement p_reqQrySttm, RetAtsStatement retAts) throws Exception {
        String[] respHeader = new String[]{"", ""};

        String tmpRespCode = "";
        String tmpRespInfo = "";

        retAts.totalNum = "0";
        int totalNum = 0;

        try {
            FtpSet ftpSet = bankFront.getFtpSet("pos");
            if (StringHelper.isNullOrEmpty(p_reqQrySttm.channel)) {
                ftpSet.downDir = StringHelper.trimEnd(ftpSet.getDownDir("pos"), "/") + "/" + p_reqQrySttm.busDate;
            } else {
                String posChannel = getBankConfig().getMapValueByKey("posChannelMapping", p_reqQrySttm.channel);
                if (StringHelper.isNullOrEmpty(posChannel)) {
                    respHeader[0] = "-1";
                    respHeader[1] = "农行供应商映射后值为空，请检查config.xml中'posChannelMapping'配置信息.";
                    return respHeader;
                }
                ftpSet.downDir = StringHelper.trimEnd(ftpSet.getDownDir("pos"), "/") + "/" + posChannel + "/" + p_reqQrySttm.busDate;
            }
            WriteBankLogLn2("农行POS对账单SFTP服务器地址:" + ftpSet.serverIP + ":" + ftpSet.port);

            StringBuilder sbFileContent = new StringBuilder();

            String tmpPosMode = getBankConfig().getValueAsString("posRecUseVersion");
            if ("B".equals(tmpPosMode)) {
                String downFileName = p_reqQrySttm.actNum + p_reqQrySttm.busDate + ".txt";
                WriteBankLogLn2("农行POS对账单所在服务器路径:" + ftpSet.downDir + "/" + downFileName);

                String localFilePath = createTempFileDirectory() + File.separator + downFileName;
                WriteBankLogLn2("农行POS对账单保存本地路径:" + localFilePath);

                FtpReceiver ftpReceiver = null;
                String posRecRequestType = getBankConfig().getValueAsString("posRecRequestType");
                if ("ftp".equals(posRecRequestType.toLowerCase())) {
                    FtpPortClient ftpPortClient = new FtpPortClient(ftpSet);
                    ftpReceiver = ftpPortClient.downloadFile(downFileName, localFilePath);
                } else if ("sftp".equals(posRecRequestType.toLowerCase())) {
                    SftpPortClient sftpPortClient = new SftpPortClient(ftpSet);
                    String sftpFilePath = StringHelper.trimEnd(ftpSet.downDir, "/") + "/" + downFileName;
                    WriteBankLogLn2("待下载SFTP服务器文件路径:\r\n" + sftpFilePath);
                    ftpReceiver = sftpPortClient.downloadFile("", sftpFilePath, localFilePath);
                }
                if (ftpReceiver.isCompleted) {
                    if (sbFileContent.length() > 0) {
                        sbFileContent.append("\n");
                    }
                    sbFileContent.append(FileHelper.readFileText(localFilePath, getCharset("UTF-8", "pos")));
                } else {
                    tmpRespCode = "-1";
                    tmpRespInfo = "农行POS对账单下载失败,原因:\r\n" + ftpReceiver.connMsg;
                }
            } else {
                tmpRespCode = "-1";
                tmpRespInfo = "对账单版本错误,当前版本为:[" + tmpPosMode + "].";
            }
            if (StringHelper.hasAnyChar(sbFileContent.toString())) {
                tmpRespCode = "0";

                String tmpStrRet = sbFileContent.toString();
                WriteBankLogLn2("农行POS对账单响应数据:\r\n" + tmpStrRet);

                StringReader strReader = new StringReader(tmpStrRet);
                BufferedReader tmpReader = new BufferedReader(strReader);

                boolean isContinue = false;
                while (true) {
                    String eachline = tmpReader.readLine();
                    if (eachline == null) {
                        break;
                    }
                    if ("".equals(eachline.trim())) {
                        continue;
                    }
                    String[] detailNodes = eachline.split("`~");
                    if (p_reqQrySttm.actNum.equals(detailNodes[1].trim())) {
                        totalNum++;
                        isContinue = true;
                        RetAtsStatementDetail tmpRetDetail = new RetAtsStatementDetail();

                        if (StringHelper.hasAnyChar(detailNodes[4])) {
                            tmpRetDetail.askNumber = detailNodes[4].trim();
                        }

                        tmpRetDetail.cdFlag = "22";

                        if (StringHelper.hasAnyChar(detailNodes[11])) {
                            tmpRetDetail.amount = StringHelper.amountDivide100(detailNodes[11].trim());
                        }

                        if (StringHelper.hasAnyChar(detailNodes[15])) {
                            tmpRetDetail.fee = StringHelper.amountDivide100(detailNodes[15].trim());
                        }

                        tmpRetDetail.busTime = detailNodes[6];

                        if (StringHelper.hasAnyChar(detailNodes[7])) {
                            tmpRetDetail.oppAct = detailNodes[7].trim();
                        }

                        if (StringHelper.hasAnyChar(detailNodes[8])) {
                            tmpRetDetail.oppActName = detailNodes[8].trim();
                        }

                        if ("2".equals(detailNodes[13].trim())) {
                            tmpRetDetail.transState = TransState.Success;
                        } else {
                            tmpRetDetail.transState = TransState.Fail;
                        }

                        retAts.writeRetDetail(tmpRetDetail);
                    }
                }

                if (!isContinue) {
                    tmpRespCode = "0";
                    tmpRespInfo = "没有符合条件的记录!";
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            tmpRespCode = "-1";
            tmpRespInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.totalNum = String.valueOf(totalNum);

        respHeader[0] = tmpRespCode;
        respHeader[1] = tmpRespInfo;

        return respHeader;
    }

    /**
     * 查询账户明细
     *
     * @param p_reqQrySttm
     * @param retAts
     * @return
     * @throws Exception
     */
    private String[] getHisRecStatement(ReqQryStatement p_reqQrySttm, RetAtsStatement retAts) {
        String[] respHeader = new String[]{"", ""};

        String tmpRespCode = "";
        String tmpRespInfo = "";

        retAts.totalNum = "0";
        int totalNum = 0;
        try {
            ABC02Header bankHeader = new ABC02Header();
            XmlTextWriter xmlWriter = new XmlTextWriter();
            bankHeader.CCTransCode = "CQRC68";
            bankHeader.ReqSeqNo = p_reqQrySttm.reqHeader.transSeqID;
            bankHeader.ReqDateTime = p_reqQrySttm.getBusDate();

            writeCommonHeader(xmlWriter, bankHeader);
            xmlWriter.writeStartElement("Cmp");
            xmlWriter.writeElementString("DbProv", getBankConfig().getMapValueByKey("dbProv" + bankHeader.CCTransCode, p_reqQrySttm.actNum));
            xmlWriter.writeElementString("DbAccNo", p_reqQrySttm.actNum);
            xmlWriter.writeElementString("DbCur", "01");
            xmlWriter.writeElementString("NFProv", "");
            xmlWriter.writeEndElement();
            xmlWriter.writeStartElement("Corp");
            String NFAccNo = getBankConfig().getMapValueByKey("nFAccNo" + bankHeader.CCTransCode, p_reqQrySttm.actNum);
            xmlWriter.writeElementString("NFAccNo", NFAccNo);
            String NVoucherType = getBankConfig().getMapValueByKey("nVoucherType" + bankHeader.CCTransCode, p_reqQrySttm.actNum);
            xmlWriter.writeElementString("NVoucherType", NVoucherType);
            xmlWriter.writeElementString("StartDate", Format.Date8Format.format(p_reqQrySttm.getBusDate()));
            xmlWriter.writeElementString("EndDate", Format.Date8Format.format(p_reqQrySttm.getBusDate()));
            xmlWriter.writeEndDocument();

            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());//发送银行
            XmlTextReader tmpBkReader;
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/ap/RespCode");
                    String tmpRetInfo = tmpBkReader.getFirstText("/ap/RespInfo");
                    String tmpRetRxtInfo = tmpBkReader.getFirstText("/ap/RxtInfo");
                    if (tmpRetCode != null && tmpRetCode.equals("0000")) {
                        int tmpRecordNum = Integer.parseInt(tmpBkReader.getFirstText("/ap/Cme/RecordNum"));
                        int tmpFieldNum = Integer.parseInt(tmpBkReader.getFirstText("/ap/Cme/FieldNum"));
                        if (tmpRecordNum > 0) {
                            String tmpDataMFS = null;
                            String tmpFileFlag = tmpBkReader.getFirstText("/ap/FileFlag");
                            if (tmpFileFlag != null && tmpFileFlag.equals("1")) {
                                String tmpBatchFileName = tmpBkReader.getFirstText("/ap/Cmp/BatchFileName");
                                String tmpFilePath = StringHelper.trimEnd(bankFront.bkTransFolder, File.separator) + File.separator + tmpBatchFileName;

                                if ("dspfileserver".equals(this.bankFront.getAccessBkFileModeLowerCase())) {
                                    this.WriteBankLogLn("读取前置数据文件：" + tmpFilePath);
                                    WriteBankLogLn("accessBkFileMode：" + bankFront.accessBkFileMode);
                                    DspClient dspClient = new DspClient(bankFront.dspFileServer);
                                    dspClient.charsetName = getCharset();
                                    TcpReceiver tcpRec = dspClient.getFile(FileType.bankFile, tmpFilePath);
                                    if (tcpRec.isCompleted) {
                                        if (tcpRec.isRtnBinaryFile) {
                                            tmpDataMFS = new String(tcpRec.recBytes, tcpRec.contentStartIndex, tcpRec.contentLength, tcpRec.charsetName);
                                        } else {
                                            String errMsg = new String(tcpRec.recBytes, tcpRec.contentStartIndex, tcpRec.contentLength, tcpRec.charsetName);
                                            WriteBankLogLn("从远程DSP（" + bankFront.dspFileServer + "）获取前置文件未完成：" + errMsg);
                                        }
                                    } else {
                                        this.WriteBankLogLn("从远程DSP（" + bankFront.dspFileServer + "）获取前置文件未完成：" + tcpRec.getConnMsg());
                                    }
                                } else if ("ftp".equals(this.bankFront.getAccessBkFileModeLowerCase())) {
                                    tmpFilePath = getTempFileDirectory() + File.separator + tmpBatchFileName;

                                    WriteBankLogLn2("结果文件保存本机路径: " + tmpFilePath);
                                    FtpSet ftpSet = bankFront.getFtpSet("");
                                    WriteBankLogLn2("ftp服务器待下载文件路径: " + ftpSet.downDir + "/" + tmpBatchFileName);
                                    FtpPortClient ftpPortClient = new FtpPortClient(ftpSet);
                                    FtpReceiver ftpReceiver = ftpPortClient.downloadFile(tmpBatchFileName, tmpFilePath);
                                    if (ftpReceiver.isCompleted) {
                                        tmpDataMFS = FileHelper.readFileText(tmpFilePath, getCharset());
                                        WriteBankLogLn2("本地批次结果文件内容:\r\n" + tmpStrRet);
                                    } else {
                                        tmpRespCode = "-1";
                                        tmpRespInfo = "文件下载失败" + ftpReceiver.connMsg;
                                        WriteBankLogLn2("文件下载失败" + ftpReceiver.connMsg);
                                    }
                                } else {
                                    this.WriteBankLogLn("读取前置数据文件：" + tmpFilePath);
                                    tmpDataMFS = FileHelper.readFileText(tmpFilePath, getCharset());
                                }

                                if (tmpDataMFS == null) {
                                    this.WriteBankLogLn("读取前置数据文件返回为null，需确认前置文件夹配置和文件是否存在");
                                } else {
                                    this.WriteBankLogStep3(tmpDataMFS);
                                }
                            } else {
                                tmpDataMFS = tmpBkReader.getFirstText("/ap/Cmp/RespPrvData1");//
                            }
                            if (tmpDataMFS != null) {
                                StringBuilder tmpSbLog = new StringBuilder();
                                ArrayList<String[]> tmpArrayList = MFSHelper.getTextArray(tmpDataMFS, "|", tmpFieldNum, tmpRecordNum, tmpSbLog);
                                if (tmpSbLog.length() == 0) {
                                    //格式如下（MFS）：账务处理状态|交易日期|交易时间|会计日期|日志号|明细顺序号|借贷标识|现转标志|
                                    //                    0         1       2        3      4       5       6       7
                                    // 对方账号省市代码|对方账号|对方账号货币码|对方账号户名|交易金额|账户余额|上笔余额|客户参考号|交易码|摘要|附言|
                                    //       8           9         10          11         12      13      14      15       16    17   18
                                    for (int i = 0; i < tmpArrayList.size(); i++) {
                                        totalNum ++;
                                        String[] tmpEachArr = tmpArrayList.get(i);
                                        RetAtsStatementDetail tmpRetDetail = new RetAtsStatementDetail();

                                        tmpRetDetail.oppAct = tmpEachArr[9];
                                        tmpRetDetail.cur = this.convertCurToATS(tmpEachArr[10]);
                                        tmpRetDetail.oppActName = tmpEachArr[11].trim();

                                        if (tmpEachArr[6].startsWith("-")) {
                                            tmpRetDetail.cdFlag = "27";
                                            tmpRetDetail.billType = "1";
                                        } else {
                                            tmpRetDetail.cdFlag = "22";
                                            tmpRetDetail.billType = "2";
                                        }
                                        tmpRetDetail.amount = tmpEachArr[12].replace("-", "");
                                        if (tmpEachArr[2].length() >= 14) {
                                            tmpRetDetail.busTime = tmpEachArr[2].substring(0, 4) + "-" + tmpEachArr[2].substring(4, 6) + "-" + tmpEachArr[2].substring(6, 8) + " " + tmpEachArr[2].substring(8, 10) + ":" + tmpEachArr[2].substring(10, 12) + ":" + tmpEachArr[2].substring(12, 14);
                                        } else {
                                            tmpRetDetail.busTime = tmpEachArr[1].substring(0, 4) + "-" + tmpEachArr[1].substring(4, 6) + "-" + tmpEachArr[1].substring(6, 8) + " " + tmpEachArr[2].substring(8, 10) + ":" + tmpEachArr[2].substring(10, 12) + ":" + tmpEachArr[2].substring(12, 14);
                                        }

                                        nodeAnalysic(tmpEachArr, tmpRetDetail, getCharset());
                                        retAts.writeRetDetail(tmpRetDetail);
                                    }
                                } else {
                                    tmpRespCode = "-1";
                                    tmpRespInfo = tmpSbLog.toString();
                                }
                            } else {
                                tmpRespCode = "-1";
                                tmpRespInfo = "数据为空";
                            }
                        }
                    } else if (!"查询无数据!".equals(tmpRetRxtInfo)) {
                        tmpRespCode = "-1";
                        if (!StringHelper.isNullOrEmpty(tmpRetRxtInfo)) {
                            tmpRespInfo = tmpRetRxtInfo;
                        } else {
                            tmpRespInfo = tmpRetInfo;
                        }
                    }
                } else {
                    tmpRespCode = "-1";
                    tmpRespInfo = tmpSbMsg.toString();
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            tmpRespCode = "-1";
            tmpRespInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.totalNum = String.valueOf(totalNum);

        respHeader[0] = tmpRespCode;
        respHeader[1] = tmpRespInfo;

        return respHeader;
    }


}
